package net.neptech.listener.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import net.neptech.model.dto.InstanceNodeRecordParamDto;
import net.neptech.listener.AbstractEventListenerStrategy;
import net.neptech.model.dto.node.Node;
import net.neptech.node.NodeDataStoreFactory;
import net.neptech.service.RemoteService;
import net.neptech.util.FlowableUtil;
import net.neptech.util.JsonUtil;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.event.impl.FlowableSequenceFlowTakenEventImpl;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Map;

import static net.neptech.enums.workflow.InstanceConstant.VariableKey.NODE_JUMP_KEY;


/**
 * 分支执行
 *
 * @author Huijun Zhao
 * @description
 * @date 2023-10-10 10:12
 */
@Slf4j
@Component
public class SequenceFlowTakenEventListener extends AbstractEventListenerStrategy implements InitializingBean {
    @Autowired
    private RemoteService remoteService;

    /**
     * 处理数据
     */
    @Override
    public void handle(FlowableEvent event) {
        FlowableSequenceFlowTakenEventImpl e = (FlowableSequenceFlowTakenEventImpl) event;
        DelegateExecution execution = e.getExecution();
        String tenantId = execution.getTenantId();
        String executionId = e.getExecutionId();
        String activityId = e.getId();
        String processInstanceId = e.getProcessInstanceId();
        String processDefinitionId = e.getProcessDefinitionId();
        String flowId = FlowableUtil.getFlowId(processDefinitionId);
        RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class);
        Node node = NodeDataStoreFactory.getInstance().getNode(flowId, activityId);
        if (node == null) {
            return;
        }
        Map<String, Object> processVariables = runtimeService.getVariables(executionId);
        {
            InstanceNodeRecordParamDto instanceNodeRecordParamDto = new InstanceNodeRecordParamDto();
            instanceNodeRecordParamDto.setFlowId(flowId);
            instanceNodeRecordParamDto.setProcessInstanceId(processInstanceId);
            instanceNodeRecordParamDto.setData(JsonUtil.toJSONString(processVariables));
            instanceNodeRecordParamDto.setNodeId(activityId);
            instanceNodeRecordParamDto.setParentNodeId(MapUtil.getStr(processVariables, StrUtil.format(NODE_JUMP_KEY, activityId)));
            instanceNodeRecordParamDto.setFlowUniqueId(FlowableUtil.getFlowUniqueId(activityId, flowId, processInstanceId, tenantId));
            instanceNodeRecordParamDto.setNodeType((node.getType()));
            instanceNodeRecordParamDto.setNodeName(node.getNodeName());
            instanceNodeRecordParamDto.setExecutionId(executionId);
            remoteService.startNodeEvent(instanceNodeRecordParamDto);
        }
        {
            InstanceNodeRecordParamDto instanceNodeRecordParamDto = new InstanceNodeRecordParamDto();
            instanceNodeRecordParamDto.setFlowId(flowId);
            instanceNodeRecordParamDto.setExecutionId(executionId);
            instanceNodeRecordParamDto.setProcessInstanceId(processInstanceId);
            instanceNodeRecordParamDto.setData(JsonUtil.toJSONString(processVariables));
            instanceNodeRecordParamDto.setNodeId(activityId);
            instanceNodeRecordParamDto.setNodeName(node.getNodeName());
            remoteService.endNodeEvent(instanceNodeRecordParamDto);
        }
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        afterPropertiesSet(FlowableEngineEventType.SEQUENCEFLOW_TAKEN.toString());
    }
}
